/**
 * Created by utkin on 19.08.14.
 *
 * @todo: распилить файл на 2 части (кол-во новых сообщений и остальной код). вторую чать подгружать динамически.
 */
var messenger = {};

///////////////////////////////////////////////////////////////////////////////////////
// Инициализация обработчиков
///////////////////////////////////////////////////////////////////////////////////////
$(function () {
	/**
	 * Обработка клавиши enter в поле ввода
	 */
	$('body').on('keydown', '#textWithSmile', function(e){
		if ((13 === e.keyCode)) {  //enter && shift
			if (e.shiftKey || e.ctrlKey) {
			} else {
				e.preventDefault();
				messenger.sendMessageCallback();
			}
		}
	});

    /**
     * Вызов обработчика события о приходе нового сообщения
     */
    $('body').on('messengerNewMessage', messenger.newMessageHandler);
    $('body').on('messengerMessageRead', messenger.messageReadHandler);

    /**
     * Обработчик клика по кнопке смены списка пользователей: Обычные, Избранные, Заблокированные
     */
    $('body').on('click', 'li.messenger-list-status > a', function () {
        var listStatus = $(this).attr('listStatus');
        messenger.updateListStatusButtons(listStatus);
        messenger.updateWindowBody(listStatus, 0, function () {
            // Извлекаем из cookies id профиля собеседника
            var companionProfileId = $.cookie('companionProfileId');
            companionProfileId = companionProfileId ? companionProfileId : 0;
            // Если мы ранее запоминали собеседника - выделяем его в списке пользователей
            if (companionProfileId != 0) {
                var userIsSelected = messenger.selectActiveUser(companionProfileId);
                // Если выделение прошло успешно (пользователь присутствует в списке),
                // загружаем переписку с ним и ставим фокус на окне ввода сообщения
                if (userIsSelected) {
                    messenger.updateMessageListArea(companionProfileId, function () {
//                    	$('#textWithSmile').KEmoji('api').focus();
                    });
                }
            }
        });

        return false;
    });

    /**
     * Обработчик клика по пользователю в списке пользователей
     */
    $('body').on('click', 'li.messenger-usersList-itemBlock', function () {
        // Извлекаем id профиля собеседника
        var companionProfileId = $(this).attr('uid');

        messenger.updateMessageListArea(companionProfileId, function () {
//        	$('#textWithSmile').KEmoji('api').focus();

			$('body').trigger('refreshWindowPart');
        });
        messenger.selectActiveUser(companionProfileId);
        // запоминаем собеседника
        $.cookie('companionProfileId', companionProfileId, {path : '/'});

        return false;
    });

    /**
     * Обработчик клика по кнопке отправки сообщения
     */
    $('body').on('click', '#messenger-message-send-button', messenger.sendMessageCallback);

    /**
     * Обработчик отправки формы с сообщением
     */
    $('body').on('submit', '#messenger-message-send-form', function () {
        messenger.sendMessageCallback();
        return false;
    });

    /**
     * Обработчик нажатия на кнопки "Добавить в избранное" и "Заблокировать"
     */
    $('body').on('click', '#messenger-messages-area-favorite, #messenger-messages-area-blocked', function () {
        // Извлекаем id профиля собеседника
        var targetProfileId = $(this).attr('targetProfileId');
        // Извлекаем новый статус отношения к группе с собеседником
        var newRelationStatus = $(this).attr('newRelationStatus');
        messenger.changeRelation(newRelationStatus, targetProfileId, function (){
        messenger.updateButtons(newRelationStatus);
        messenger.updateUsersList(newRelationStatus, targetProfileId);
        messenger.updateMessageListArea(targetProfileId, function () {
//        	$('#textWithSmile').KEmoji('api').focus();

			$('body').trigger('refreshWindowPart');
        });
        });
        return false;
    });

    /**
     * Обработчик нажатия на кнопки Удалить пользователя
     */
    $('body').on('click', '#messenger-messages-area-delete', function () {
        // Извлекаем id профиля собеседника
        var targetProfileId = $(this).attr('targetProfileId');
        // Извлекаем новый статус отношения к группе с собеседником
        var newRelationStatus = $(this).attr('newRelationStatus');
        //текущий статус
        var listStatus = $('li.messenger-list-status.active > a').attr('liststatus');
        messenger.changeRelation(newRelationStatus, targetProfileId, function (){
        messenger.updateUsersList(listStatus, targetProfileId);
        });
        $.cookie('companionProfileId',0, {path : '/'});
		messenger.updateWindowBody(listStatus, 0);
		return false;
    });

    /**
     * Закрытие окна по нажатию на кнопку "messages" в хидере
	 * @return boolean
     */
    $('body').on('click', 'a[href=#messenger]', function () {
        // Если окно открыто - закрываем
        if (window.app.checkModal('messenger')) {
            window.app.closeModal(false);
            return false;
        }

		return true;
    });

    /**
     * Открытие диалога с пользователем по клику на кнопку "Send message"
     */
    $('body').on('click', '.up-send-message, .send-message', function () {
        // Извлекаем id профиля собеседника
        var companionProfileId = $(this).attr('uid');
        // Запоминаем его в cookies
        $.cookie('companionProfileId', companionProfileId, {path : '/'});
        // Обновляем адресную строку: добавляем '#messenger'
        window.app.navigate('messenger', {trigger: true, replace: false});
        return false;
    });

    /**
     * Обработчик клика по кнопке "предыдущие сообщения" в списке собщений
     */
    $('body').on('click', '#messenger-messages-pagination-button a', function () {
        // Извлкекаем время последнего видимого сообщения
        var beforeTimestamp = $(this).attr('beforeTimestamp');
        // Извлекаем идентификатор группы
        var groupId = $(this).attr('gid');
        // Извлекаем id профайла собеседника
        var companionProfileId = $(this).attr('cid');
        messenger.getNextPage(groupId, companionProfileId, beforeTimestamp, function (data) {
            $('#messenger-messages-pagination-button').replaceWith(data);
        });
        return false;
    });

    /**
     * Обработчик нажатия на кнопки "Добавить в избранное" на странице профиля пользователя
     */
    $('body').on('click', '#profile-add-to-fav-button', function () {
        // Извлекаем id профайла собеседника
        var targetProfileId = $(this).attr('targetProfileId');
        // Извлекаем новый статус отношения к группе, в которой есть собеседник
        var newRelationStatus = $(this).attr('newRelationStatus');
        messenger.changeRelation(newRelationStatus, targetProfileId, function(){
            $.get(
                '~profiles.favButton',
                {
                    'targetProfileId': targetProfileId
                },
                function (data) {
                    // Заменяем кнопку "Добавить в избранное" новой, полученной в ответе
					$('#profile-add-to-fav-button').tooltip('hide');
                    $('#profile-add-to-fav-button').replaceWith(data);
					$('#profile-add-to-fav-button').tooltip('show');
					
					// если установили избранного - добавляем к в счетчик избранных единицу, иначе вычитаем
					if (1 == $(data).attr("newrelationstatus")) {
						$('#favorite-count').text(parseInt($('#favorite-count').text())+1);
					} else {
						$('#favorite-count').text(parseInt($('#favorite-count').text())-1);						
					}
					
                }
            );
        });
        return false;
    });

    /**
     * добавляем функцию в прототип jquery для фильтрации текста
	 * @return boolean
     */
    $.expr[':'].Contains = function(a,i,m){
    	return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase())>=0;
    };


    /**
     * Фильтр списка пользователей
     */
	$('body').on('change', '.input-search-block input', function() {
		var filter = $(this).val();
		if (filter) {
			var list = $('#messenger-users-list li');
			var matches = list.find('.mdu-name:Contains("'+ filter +'")').parent();
			list.not(matches).hide();
			matches.show();
		} else {
			$('#messenger-users-list li').show();
		}
		return false;
	}).on('keyup', '.input-search-block input', function() {
		$(this).change();
	});
});
// /////////////////////////////////////////////////////////////////////////////////////
// Методы мессенджера
///////////////////////////////////////////////////////////////////////////////////////

/**
 * Отмечает активного пользователя в списке пользователей.
 * Возвращает true, если пользователь был успешно отмечен, как активный (присутствовал в списке пользователей)
 *
 * @param uid - идентификатор профиля собеседника
 * @return {boolean}
 */
messenger.selectActiveUser = function (uid) {
    $('li.messenger-usersList-itemBlock').removeClass('active');
    // Ищем в списке пользователей блок пользователя с указанным id
    var userBlock = $('li.messenger-usersList-itemBlock[uid="' + uid + '"]');
    // Если нашли - отмечаем блок, как активный
    if (userBlock.attr('uid')) {
        userBlock.addClass('active');
        return true;
    }

    return false;
};

/**
 * Отмечает активную кнопку списка пользователей
 *
 * @param listStatus - статус группы
 */
messenger.updateListStatusButtons = function (listStatus) {
    $('.messenger-list-status').removeClass('active');
    $('li.messenger-list-status > a[listStatus=' + listStatus + ']').parent(null).addClass('active');
};

/**
 * Обновляет область со списком пользователей
 *
 * @param listStatus - статус списка
 * @param companionProfileId - id профиля собеседника
 */
messenger.updateUsersList = function (listStatus, companionProfileId) {
    $.get(
        '~messenger.users.list',
        {
            listStatus: listStatus,
            companionProfileId: companionProfileId
        },
        function (data) {
            $('#messenger-users-list').html(data);
            $('body').trigger('refreshWindowPart');
        }
    );
};

/**
 * Обновляет область переписки с пользователем
 *
 * @param companionProfileId - id профиля собеседника
 * @param callback - функция, которая отрабатывает после получения ответа от сервера
 */
messenger.updateMessageListArea = function (companionProfileId, callback) {
    $.get(
        '~messenger.messages.area',
        {
            companionProfileId: companionProfileId
        },
        function (data) {
			var myProfileId = $('[data-myProfileId]').attr('data-myProfileId');
			var groupId = $('li.messenger-usersList-itemBlock[uid=' + companionProfileId + ']').attr('data-gid');
            $('#messenger-messages-area').html(data);
            $('body').trigger('refreshWindowPart');
            $(".md-messages-block").animate({"scrollTop":100000}, 0);

            // Если callback указан - запускаем его
            if (callback) {
                callback();
            }

			messenger.updateGroupMessagesCount(groupId, myProfileId);
			messenger.updateAllMessagesCount(myProfileId);

			var listStatus = $('li.messenger-list-status.active > a').attr('listStatus');
			messenger.updateButtonUnseenMessagesCount(listStatus);
        }
    );
};

/**
 * Отправляет сообщение на сервер
 *
 * @param groupId - id группы переписки
 * @param myProfileId - id профиля
 * @param companionProfileId - id профиля собеседника
 * @param message - текст сообщения
 * @param csrfToken - csrf токен
 * @param callback - обработчик, который вызывается после доставки сообщения на сервер
 */
messenger.sendMessage = function (groupId, myProfileId, companionProfileId, message, csrfToken, callback) {

    // Если область ввода сообщения пустая или состоит из пробельных символов - не отправляем сообщение
	var clearedMsg = message;
    if (clearedMsg.replace(new RegExp('<br>', 'g'), '').trim().length < 1) {
        return false;
    }

	var formAction = $('form#messenger-message-send-form').attr('action');

    $.post (
		formAction,
        {
            ___: csrfToken,
            groupId: groupId,
            myProfileId: myProfileId,
			companionProfileId: companionProfileId,
            text: message
        },
        callback
    );
    return true;
};

/**
 * Обработчик клика по кнопке "SEND" на форме отправки сообщения
 *
 * @returns {boolean}
 */
messenger.sendMessageCallback = function () {
    var form = $('#messenger-message-send-form');
    // Извлекаем id группы переписки
    var groupId = form.attr('groupId');
    // Извлекаем id своего профиля
    var myProfileId = form.attr('myProfileId');
    // Извлекаем id профиля собеседника
    var companionProfileId = form.attr('companionProfileId');
    // Извлекаем csrf токен
    var csrfToken = $('#messenger-message-send-form input[name=___]').val();
    // Извлекаем текст сообщения
//    var message = $('#textWithSmile').KEmoji('api').getValue(KEmoji.TEXT_VALUE);
    var message = $('#textWithSmile').val();
    $('#messenger-message-send-form input[name=text]').val('');
    messenger.sendMessage(groupId, myProfileId, companionProfileId, message, csrfToken, function (data) {
    	messenger.sendMessageHandler(data, companionProfileId);
    });

    return false;
};

messenger.sendMessageHandler = function(data, companionProfileId) {
	if (! /[a-f\d]{24}/.test(data)) {
		return;
	}

	messenger.loadNewMessage(data);

	// по отправке сообщения тушим всё, зажигаем надпись о том, 
	// что пользователь не прочитал сообщение
	$(".md-messages-block .msg-log-empty").hide();
	$(".md-messages-block .msg-log-read").hide();
	$(".md-messages-block .msg-log-not-read").show();
	
	//$('div.md-last-seen').before(data);
	$('body').trigger('refreshWindowPart');
	
	// @todo: избавиться от зависимости autosize
	autosize.update($('#textWithSmile').val('')[0]);
	$('#textWithSmile').focus();

//	$('.Emoji_Input > div').text('');
	//// Прокручиваем область сообщений к последнему сообщению
	$(".md-messages-block").animate({"scrollTop":100000}, 0);
	var listStatus = $('li.messenger-list-status.active > a').attr('liststatus');
	messenger.updateUsersList(listStatus, companionProfileId);
};

/**
 * Обновляет область, включающую список пользователей и область вывода сообщений
 *
 * @param listStatus - статус списка
 * @param companionProfileId - id профиля собеседника
 * @param callback - обработчик, который вызывается после загрузки области
 */
messenger.updateWindowBody = function (listStatus, companionProfileId, callback) {
    $.get(
        '~messenger.window.body',
        {
            listStatus: listStatus,
            companionProfileId: companionProfileId
        },
        function (data) {
            $('#messenger-window-body').html(data);
            $('body').trigger('refreshWindowPart');

            // Если callback указан - запускаем его
            if (callback) {
                callback();
            }
        }
    );
};

/**
 * Обновляет кнопки списков отношений (запрос html с сервера)
 *
 * @param listStatus - статус списка
 */
messenger.updateButtons = function (listStatus) {
    $.get(
        '~messenger.buttons',
        {
            listStatus: listStatus
        },
        function (data) {
            $('#messenger-buttons').html(data);
            $('body').trigger('refreshWindowPart');
        }
    );
};

/**
 * Изменение отношения к пользователю
 *
 * @param newRelationStatus - новый статус отношения к группе
 * @param targetProfileId - id профиля собеседника
 * @param callback - обработчик, который вызывается после смены отношения
 */
messenger.changeRelation = function (newRelationStatus, targetProfileId, callback) {
    $.get(
        '~messenger.changerelation',
        {
            newRelationStatus: newRelationStatus,
            targetProfileId: targetProfileId
        },
        callback
    );
};

/**
 * Создает новую группу общения с новым собеседником, если ее еще нет.
 *
 * @param newProfileId - id профиля собеседника
 * @param callback - обработчик, который вызывается после ответа от сервера
 */
messenger.newDialog = function (newProfileId, callback) {
    $.post(
        '~messenger.newdialog',
        {
            newProfileId: newProfileId
        },
        function () {
            // Если callback указан - запускаем его
            if (callback) {
                callback();
            }
        }
    );
};

/**
 * Подгружает следующую страницу сообщений
 *
 * @param groupId - id группы общения
 * @param companionProfileId -  id профиля собеседника
 * @param beforeTimestamp - timestamp сообщения, относительно которого будет выбираться предыдущая страница
 * @param callback - обработчик, который вызывается после ответа от сервера
 */
messenger.getNextPage = function (groupId, companionProfileId, beforeTimestamp, callback) {
    $.post(
        '~messenger.messages.listbody',
        {
            groupId: groupId,
            companionProfileId: companionProfileId,
            beforeTimestamp: beforeTimestamp
        },
        function (data) {
            // Если callback указан - запускаем его
            if (callback) {
                callback(data);
            }
        }
    );
};

messenger.updateGroupMessagesCount = function (groupId, targetProfileId, force) {
	$.get('~messenger.users.unreadMessagesCount',
		{
			groupId: groupId,
			targetProfileId: targetProfileId
		},
		function(data) {
			var userBlockSelector = 'li.messenger-usersList-itemBlock[data-gid=' + groupId + ']';
			$(userBlockSelector + ' .messages-count').replaceWith(data);
		}
	);
};

messenger.updateAllMessagesCount = function (targetProfileId) {
	$.get('~messenger.messagesCount',
		{
			targetProfileId: targetProfileId
		},
		function(data) {
			$('#messenger-all-messages-count').replaceWith(data);
		}
	);
};

messenger.loadNewMessage = function (messageId) {
	$.get('~messenger.messages.ajaxItem',
		{
			messageId: messageId
		},
		function(data) {
			messenger.addMessageIntoList(data);
			$(".md-messages-block").animate({"scrollTop":100000}, 0);
		}
	);
};

messenger.addMessageIntoList = function(messageHtml) {
	var newMessageOrder = parseInt($(messageHtml).attr('order'));
	var inserted = false;
	$('div.md-message').each(function(index, value){
		var currentOrder = parseInt($(this).attr('order'));

		if (currentOrder > newMessageOrder) {
			$(this).before(messageHtml);
			inserted = true;
		}
	});

	if (!inserted) {
		$('div.md-last-seen').before(messageHtml);
	}
	window.refreshTimes();
};

messenger.updateUnseenMessagesCounters = function () {
	var myProfileId = $('[data-myProfileId]').attr('data-myProfileId');
	var groupId = '';

	var companionProfileId = $.cookie('companionProfileId');
	if (companionProfileId) {
		var userBlockSelector = 'li.messenger-usersList-itemBlock[uid=' + companionProfileId + ']';
		groupId = $(userBlockSelector).attr('data-gid');

		messenger.updateAllMessagesCount(myProfileId);

		if (groupId && groupId.length > 0) {
			messenger.updateGroupMessagesCount(groupId, myProfileId);
		}
	}

	var listStatus = $('li.messenger-list-status.active > a').attr('liststatus');
	if (listStatus !== undefined) {
		messenger.updateButtonUnseenMessagesCount(listStatus);
	}
};

messenger.loadUser = function (userProfileId, params) {
	var groupId = $('li.messenger-usersList-itemBlock[uid=' + params.data.authorId + ']').attr('data-gid');
	var myProfileId = $('[data-myProfileId]').attr('data-myProfileId');

	$.get('~messenger.users.item',
		{
			myProfileId: myProfileId,
			itemProfileId: userProfileId,
			groupId: params.data.groupId
		},
		function(data) {
			$('#messenger-users-list > ul:first').prepend(data);

			if (params) {
				params.data.isFirstGroupMessage = 0;
				messenger.newMessageHandler(params.event, params.data);
			}
		}
	);

}

messenger.updateLastSeenTime = function(targetProfileId, readTimestamp) {
	$.get('~messenger.messages.readStatus',
		{
			targetProfileId: targetProfileId,
			readTimestamp: readTimestamp
		},
		function(data) {
			var lastSeenBlock = $('div.md-last-seen');
			lastSeenBlock.replaceWith(data);
			window.refreshTimes();
			$(".md-messages-block").animate({"scrollTop":100000}, 0);
		}
	);
};

messenger.updateButtonUnseenMessagesCount = function (listStatus) {
	$.get(
		'~messenger.buttonUnseenMessages',
		{
			listStatus: listStatus
		},
		function (data) {
			var buttonCounter = $('a[liststatus=' + listStatus + '] > span.button-unseen-messages-count');
			buttonCounter.replaceWith(data);
		}
	);
}

///////////////////////////////////////////////////////////////////////////////////////
// Long-pulling обработчики
///////////////////////////////////////////////////////////////////////////////////////

/**
 * Обработчик события о приходе нового сообщения
 *
 * @param event
 * @param data
 */
messenger.newMessageHandler = function (event, data) {

	var userBlockSelector = 'li.messenger-usersList-itemBlock[uid=' + data.authorId + ']';
	
	// пришло новое сообщение - тущим всё кроме надписи о необходимости ответить
	$(".md-messages-block .msg-log-empty").hide();
	$(".md-messages-block .msg-log-not-read").hide();
	$(".md-messages-block .msg-log-read").show();
	
	// Если с пользователем раньше не общались
	if ((data.isFirstGroupMessage == 1) && ($(userBlockSelector).length == 0)) {
		var params = {};
		params.event = event;
		params.data = data;
		// Подгружаем пользователя в список пользователей
		messenger.loadUser(data.authorId, params);

		return;
	}

	var myProfileId = $('[data-myProfileId]').attr('data-myProfileId');

	// Перемещаем автора сообщения в начало списка пользователей
	$(userBlockSelector).prependTo('#messenger-users-list > ul:first');

	var messengerIsOpen = window.app.checkModal('messenger');

	// Если открыто окно мессенджера и переписка ведется с автором сообщения - подгружаем в окно переписки новое сообщение
	if (messengerIsOpen && $(userBlockSelector).hasClass('active')) {
		messenger.loadNewMessage(data.messageId);
	}
	// Иначе - обновляем количество сообщений от написавшего
	else {
		messenger.updateGroupMessagesCount(data.groupId, myProfileId);
		messenger.updateAllMessagesCount(myProfileId);

		if (data.listStatus) {
			messenger.updateButtonUnseenMessagesCount(data.listStatus);
		}
	}
};

messenger.messageReadHandler = function (event, data) {
	var readerBlock = $('li.messenger-usersList-itemBlock[uid=' + data.readerId + ']');

	if (readerBlock.hasClass('active')) {
		messenger.updateLastSeenTime(data.readerId, data.readTimestamp);
	}
};
